#!/usr/bin/python

class Position():
    #def __init__(self, amount, cost, account='-', tags=[]):
    def __init__(self, **kargs):
        #amount, cost, account='-', tags=[]):
        self.amount = kargs.get('amount')
        self.cost = kargs.get('cost')
        self.account = kargs.get('account')
        #self.amount, self.cost = amount, cost
        #self.account = account
        tags = kargs.get('tags', [])
        if isinstance(tags, list):
            self.tags = tags
        else:
            self.tags = [tags]
    @property
    def paid(self):
        return self.amount * self.cost

class Share():
    def __init__(self, _id, _data):
        self.id = _id
        self.name, self.cur, self.low, self.high, \
        self.rate, self.last = tuple(_data[0:6])
        self.positions = []
        self.compen = 0
        self.upd_time = _data[-1]
    def add_position(self, pos):
        self.positions.append(Position(**pos))

    @property
    def amount(self):
        return sum(p.amount for p in self.positions)
    @property
    def has_position(self):
        return self.amount > 0
    @property
    def cost(self):
        if self.has_position:
            return sum(p.paid for p in self.positions)
        return 0
    @property
    def cost_ps(self):
        if self.has_position:
            return self.cost / self.amount
        return 0
    @property
    def paid(self):
        if self.has_position:
            return self.cost - self.compen
        return 0
    @property
    def value(self):
        if self.has_position:
            return sum(p.amount * self.cur for p in self.positions)
        return 0
    @property
    def prevalue(self):
        if self.has_position:
            return sum(p.amount * self.last for p in self.positions)
        return 0
    @property
    def revenue(self):
        if self.has_position:
            return self.value - self.paid
        return 0
    @property
    def diff(self):
        if self.has_position:
            return self.value - self.prevalue
        return 0
    @property
    def profit_rate(self):
        if self.has_position:
            return self.value * 100 / self.paid - 100
        return 0
    @property
    def tags(self):
        if self.has_position:
            return [t for p in self.positions if p.tags for t in p.tags]
        return []

    def get_panel_lines(self):
        _lines = []
        _lines.append(f'{self.id} {self.name}')
        _lines.append(f'Cur.: {self.cur:7.2f} ({self.rate:2.2f}%)')
        _lines.append(f'Last: {self.last:7.2f}')
        if self.positions:
            _lines.append(f'Cost: {self.cost_ps:7.2f} ({self.profit_rate:2.2f}%)')
            _lines += [f'{p.account:>5} {p.cost:7.2f} {p.amount}' for p in self.positions]
        if self.compen != 0:
            _lines.append(f'Compen: {self.compen:9.2f}')
            _back_target = (self.cost - self.compen) / self.amount
            _lines.append(f'Target: {_back_target:9.2f}')
        return _lines

class ShareGroup():
#    def __init__(self, name, share_ids):
#        self.shares = []
#        self.name = name
#        self.share_ids = share_ids
    def __init__(self, obj_dict):
        self.shares = []
        self.name = obj_dict['name']
        self.share_ids = [sid.lower() for sid in obj_dict.get('stocks', [])]
        self.reference = obj_dict.get('reference', '')

        self.current_share_id = ''
#        if 'summary' in obj_dict:
#            self.summary = obj_dict['summary']
#        else:
#            self.summary = None
        self.upd_time = 'UNKNOWN'
        self.resp_time = 0
    @classmethod
    def load_groups(cls, obj_list):
        return [cls(o) for o in obj_list]

    def update(self, _args):
        _rt = _args.get('rt', {})
        _pos = _args.get('pos', [])
        ## py3
        ## self.shares.clear()
        ## all
        del self.shares[:]
        for s in [
                Share(sid, _rt[sid]) for sid in self.share_ids if sid in _rt]:
            p = [_p for _p in _pos if _p['id'] == s.id]
            if p:
                pos = p[0]
                if isinstance(pos['count'], list):
                    for _p in pos['count']:
                        s.add_position(_p)
                    if 'tags' in pos:
                        s.positions[0].tags = pos['tags']
                else:
                    s.add_position({
                        'cost': pos['cost'],
                        'amount': pos['count'],
                        'tags': pos.get('tags', [])
                    })
                if 'compen' in pos:
                    s.compen = pos['compen']
            self.shares.append(s)
        if self.shares:
            self.upd_time = self.shares[-1].upd_time
        self.resp_time = _rt['resp_time']

    def get_prev(self):
        if not self.shares:
            return ''
        _cur = self.current_share_id
        if _cur:
            _shares = [s for s in self.shares if s.id == _cur]
            if not _shares:
                return ''
            _cur_share = _shares[-1]
            _prev = (self.shares.index(_cur_share) - 1) % len(self.shares)
            _cur = self.shares[_prev].id
        else:
            _cur = self.shares[-1].id
        self.current_share_id = _cur
        return _cur

    def get_next(self):
        if not self.shares:
            return ''
        _cur = self.current_share_id
        if _cur:
            _shares = [s for s in self.shares if s.id == _cur]
            if not _shares:
                return ''
            _cur_share = _shares[0]
            _next = (self.shares.index(_cur_share) + 1) % len(self.shares)
            _cur = self.shares[_next].id
        else:
            _cur = self.shares[0].id
        self.current_share_id = _cur
        return _cur

    @property
    def selected_line_no(self):
        _share = self.selected_share
        if not _share:
            return -1
        _index = self.shares.index(_share)
        lineno = _index + len(
            [s for s in self.shares[:_index] if s.has_position]
        )
        if _share.has_position:
            lineno += 1
        return lineno

    @property
    def selected_share(self):
        if not self.current_share_id:
            return None
        return  next(
            iter([s for s in self.shares if s.id == self.current_share_id]),
            None
        )

    @property
    def summary(self):
        return {
            'count': len(self.shares),
            'up': len([s for s in self.shares if s.cur >= s.last]),
            'down': len([s for s in self.shares if s.cur < s.last]),
            'value': sum(s.value for s in self.shares),
            'cost': sum(s.paid for s in self.shares),
            'revenue': sum(s.revenue for s in self.shares),
            'diff': sum(s.diff for s in self.shares)
        }


class IndexGroup(ShareGroup):
    def __init__(self):
        super().__init__({
            'name': 'Indics',
            'stocks': ['sh000001', 'sz399001', 'sz399006']
        })


if __name__ == '__main__':

    _records = {
        '600618': [
            '600618', 1, 2, 3, 4, 5, 6, 7, 8, 9, '2020-06-11 16:27'
        ],
        'resp_time': 50
    }
    _pos = [
        {
            "abbr": "PingAn",
            "id": "600618",
            "cost":85.50,
            "count":2000,
            "tags": ["GOOD"]
        }
    ]
    sg = ShareGroup({
        'name': 'group1',
        'stocks': ['600618'],
        'summary': [0, 1]
    })

    sg.update({'rt': _records, 'pos': _pos})

    for _share in sg.shares:
        print(_share.__dict__)
        print(' | '.join(_share.tags))
